#include <obj_parser.h>
#include <fstream>
#include <string>
#include <cstdio>
#include <stdexcept>

Mesh ObjParser::Parse(std::filesystem::path objPath) {
    std::ifstream objStream;
    objStream.open(objPath);
    if (!objStream.is_open()) {
        std::string error =  std::string("failed to open file ") + objPath.string() +
                             std::string(" in line ") + std::to_string(__LINE__) + 
                             std::string(" in file ") + std::string(__FILE__);
        throw std::runtime_error(error);
    }

    Mesh mesh;

    std::string line;
    while (std::getline(objStream, line)) {
        size_t space = line.find(' ');
        std::string token = line.substr(0, space);
        if (token == "v") {
            mesh.vertices.push_back(
                parseVertex(line.substr(space + 1, line.size())));
        }
        else if (token == "vt") {
            mesh.texCoords.push_back(
                parseTexCoord(line.substr(space + 1, line.size())));
        }
        else if (token == "vn") {
            mesh.normal.push_back(
                parseNormal(line.substr(space + 1, line.size())));
        }
        else if (token == "f") {
            mesh.indices.push_back(
                parseIndex(line.substr(space + 1, line.size())));
        }
    }

    return mesh;
}

Mesh::TriangleIndex ObjParser::parseIndex(std::string_view value) {
    size_t space = value.find(' ');
    Mesh::TriangleIndex triangleIndex;

    triangleIndex[0] = parseVertexIndex(value.substr(0, space));
    size_t nextSpace = value.find(' ', space + 1);
    triangleIndex[1] = parseVertexIndex(value.substr(space + 1, nextSpace));
    triangleIndex[2] = parseVertexIndex(value.substr(nextSpace + 1, value.size()));

    for (auto& index : triangleIndex) {
        --index[0];
        --index[1];
        --index[2];
    }

    return triangleIndex;
}